<?php

@session_start();
function redirecterrpage()
{
    ?>
    <script>
        window.location='error.php';
    </script>
    <?php
}

include_once "config.php";
require("Log.class.php");
if (!extension_loaded("pdo")) die("Missing PDO PHP extension."); // check if extension loaded
class DB {
	public static $conn = NULL;
	public static $err = NULL;
    public static $dbname;
	public static $hostname;
	public static $dbusername;
	public static $dbpassword;
	public static $numofrows=0;
	public static $affectedrows=0;
    public static $portnumber=3306;
    public static $dbtype="mysql";
    
    private static $path = '/logs/';
    
    # @object, The PDO object
	private static $pdo;
    
    # @object, PDO statement object
	private static $succes;
    
	# @object, PDO statement object
	private static $sQuery;

	# @array,  The database settings
	private static $settings;

	# @bool ,  Connected to the database
	private static $bConnected = false;

	# @object, Object for logging exceptions	
	private static $log;

	# @array, The parameters of the SQL query
	private static $parameters;
    
	/**
	 * Connects to SQL Server
	 * 
	 * @return	true/false
	 */
   
   function __construct(){
    
        self::$log = new Log();	
        self::$parameters = array();
        
        self::$dbname=DBNAME;
        self::$hostname=HOST;
        self::$dbusername=USERNAME;
        self::$dbpassword=PASSWORD;
        self::$dbtype=TYPE;
        self::$portnumber=PORTNUMBER;
   }
     
   public static function connect()
	{
	    $dsn = 'mysql:dbname='.self::$dbname.';host='.self::$hostname.'';
		try 
		{
			# Read settings from INI file, set UTF8
			self::$pdo = new PDO($dsn, self::$dbusername, self::$dbpassword, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
			
            	
			
			# check forobject persistance
			self::$pdo->setAttribute(PDO::ATTR_PERSISTENT, true);
            
            # We can now log any exceptions on Fatal error. 
			self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			
            
            # Disable emulation of prepared statements, use REAL prepared statements instead.
			self::$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
			
			# Connection succeeded, set the boolean to true.
			return self::$bConnected = true;
            
		}
		catch (PDOException $e) 
		{
			# Write into log
			
            self::$err = $e->getMessage();
            self::ExceptionLog($e->getMessage(), $query );
            $_SESSION['pdoerror']=$e->getMessage()." in ".$query ;
			redirecterrpage();
			exit();
		}
		
	}
    
	
	
	/*
	 * close the database connection
	 */
	public static function close () {
		self::$conn = NULL;
	}
    
    /**
	*	Every method which needs to execute a SQL query uses this method.
	*	
	*	1. If not connected, connect to the database.
	*	2. Prepare Query.
	*	3. Parameterize Query.
	*	4. Execute Query.	
	*	5. On exception : Write Exception into the log + SQL query.
	*	6. Reset the Parameters.
	*/	
		private static function Init($query,$parameters = "")
		{
		# Connect to database
		if(!self::$bConnected) { self::Connect(); }
		try {
				# Prepare query
				//self::$sQuery = self::$pdo->prepare($query);
				
                /*
                if(is_array($parameters) && !empty($parameters))
    				self::$sQuery->execute($parameters);
    			else
    				self::$sQuery->execute();
                */
			     # Prepare query
				self::$sQuery = self::$pdo->prepare($query);
				
				# Add parameters to the parameter array	
				self::bindMore($parameters);

				# Bind parameters
				if(!empty(self::$parameters)) {
					foreach(self::$parameters as $param)
					{
						$parameters = explode("\x7F",$param);
						self::$sQuery->bindParam($parameters[0],$parameters[1]);
                        
					}		
				}

				# Execute SQL 
				$execobj= self::$succes 	= self::$sQuery->execute();	
                
                if($execobj)
                {
                    self::$affectedrows=1;
                }
                else
                {
                    self::$affectedrows=0;
                }
                
			}
			catch(PDOException $e)
			{
					# Write into log and display Exception
					//echo $this->ExceptionLog($e->getMessage(), $query );
					//die();
                    self::ExceptionLog($e->getMessage(), $query );
                    $_SESSION['pdoerror']=$e->getMessage()." in ".$query ;
					redirecterrpage();
                    exit();
			}

			# Reset the parameters
			self::$parameters = array();
		}
		
        public static function reviseArray($parameterarr=array())
        {
            $revisedarr=array();
            if($parameterarr!=null)
            {
                foreach($parameterarr as $key=>$value)
                {
                    $revisedarr[str_ireplace(":","",$key)]=$value;
                }    
            }
            return $revisedarr;
        }
        
        
       /**
	*	@void 
	*
	*	Add the parameter to the parameter array
	*	@param string $para  
	*	@param string $value 
	*/	
		public static function bind($para, $value)
		{	
			self::$parameters[sizeof(self::$parameters)] = ":" . $para . "\x7F" . $value;
		}
       /**
	*	@void
	*	
	*	Add more parameters to the parameter array
	*	@param array $parray
	*/	
		public static function bindMore($parray)
		{
			if(empty(self::$parameters) && is_array($parray)) {
				$columns = array_keys($parray);
				foreach($columns as $i => &$column)	{
					self::bind($column, $parray[$column]);
				}
			}
		}
       /**
	*   	If the SQL query  contains a SELECT statement it returns an array containing all of the result set row
	*	If the SQL statement is a DELETE, INSERT, or UPDATE statement it returns the number of affected rows
	*
	*   	@param  string $query
	*	@param  array  $params
	*	@param  int    $fetchmode
	*	@return mixed
	*/			
		public static function queryold($query,$params = null, $fetchmode = PDO::FETCH_ASSOC)
		{
			$query = trim($query);

			self::Init($query,$params);

			# The first six letters of the sql statement -> insert, select, etc...
			$statement = strtolower(substr($query, 0 , 6));
			
			if ($statement === 'select') {
				return self::$sQuery->fetchAll($fetchmode);
			}
			elseif ( $statement === 'insert' ||  $statement === 'update' || $statement === 'delete' ) {
				return self::$sQuery->rowCount();	
			}	
			else {
				return NULL;
			}
		}
	
	/**
	 * Sends a database query to SQL server.
	 *
	 * @param	string		self::res 		a database query
	 * @param	array		self::bind 		
	 * @return 	integer					id of the query result
	 */
	public static function query($query,$params = null, $fetchmode = PDO::FETCH_ASSOC)
    {
    	$query = trim($query);
        $params = self::reviseArray($params);
    
    	self::Init($query,$params);
    
    	# The first six letters of the sql statement -> insert, select, etc...
    	$statement = strtolower(substr($query, 0 , 6));
    	
        //self::$affectedrows=self::$sQuery->rowCount();
        
    	return self::$sQuery;	
    	
    }
    
    
	
	/**
	 * Gets a row from SQL database query result.
	 *
	 * @param	string		self::res		a database query
	 * @return 				array		a row from result
	 */
	
    public static function fetch_array($resultset, $fetchmode = PDO::FETCH_ASSOC)
    {
    	$row= $resultset->fetchAll($fetchmode);
    	for($i=0;$i<count($row);$i++)
		{
			foreach($row[$i] as $key=>$value)
			{
				$row[$i][$key]=trim(stripcslashes($value));
			}
		}
		return $row;
    }


    public static function fetch_num_of_rows ($res,$fetchmode = PDO::FETCH_ASSOC) {
		
        try
        {
            # Affected Rows?
			self::$affectedrows=$res->rowCount(); // 1
			$row = $res->fetchAll($fetchmode);
			
			for($i=0;$i<count($row);$i++)
			{
				foreach($row[$i] as $key=>$value)
				{
					$row[$i][$key]=trim(stripcslashes($value));
				}
			}
			return count($row);
         }
         catch (PDOException $e) {
			self::$err = $e->getMessage();
            self::ExceptionLog($e->getMessage());
            $_SESSION['pdoerror']=$e->getMessage();
            redirecterrpage();
			exit();
		} 
	}
	
	/**
	 * return the last insert id
	 */
	public static function last_id () {
		return self::$conn->lastInsertId();
        
	}
	
	/**
	 * Returns SQL error number for last error.
	 *
	 * @return 	integer		MySQL error number
	 */
	public static function error () {
		return self::$err;
	}
    
    public static function updatecheckExistance($tablename,$conditionarr=array(),$idconditionarray=array())
    {
        $selectquery=self::createSelectquerybasedonparams($tablename,$conditionarr);
        $bindarray=self::getBindarray($conditionarr);
        if(count($idconditionarray)>0)
        {
            $selectquery.=" and id != :id";
            $bindarray[":id"]=$idconditionarray['id'];
        }
        $fetchinfo=self::fetch_array(self::query($selectquery,$bindarray));
        if(count($fetchinfo)>0)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    public static function checkExistance($tablename,$conditionarr=array())
    {
        $selectquery=self::createSelectquerybasedonparams($tablename,$conditionarr);
        $bindarray=self::getBindarray($conditionarr);
        $fetchinfo=self::fetch_array(self::query($selectquery,$bindarray));
        if(count($fetchinfo)>0)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    public static function insertData($tablename,$fieldarray=array())
    {
        $insertquery=self::createInsertquerybasedonparams($tablename,$fieldarray);
        $bindarray=self::getBindarray($fieldarray);
        self::query($insertquery,$bindarray);
    }
    
    public static function updateData($tablename,$fieldarray=array(),$conditionarray=array())
    {
        $updatequery=self::createUpdatequerybasedonparams($tablename,$fieldarray,$conditionarray);
        $resultarray = array_merge($fieldarray, $conditionarray);
        $bindarray=self::getBindarray($resultarray);
        self::query($updatequery,$bindarray);
    }
    
    
    public static function deleteData($tablename,$conditionarray=array())
    {
        $deletequery=self::createDeletebasedonparams($tablename,$conditionarray);
        $bindarray=self::getBindarray($conditionarray);
        self::query($deletequery,$bindarray);
    }
    public static function createSelectquerybasedonparams($tables="users",$fieldarray=array())
    {
        $sqlquery="select * from ".$tables;
        if(count($fieldarray)>0)
        {
            $sqlquery.=" where ";
            foreach($fieldarray as $key=>$value)
    		{
    			$sqlquery.=$key."=:".$key." and ";
    		}
            $sqlquery=substr($sqlquery,0,strlen($sqlquery)-4);
        }
        return $sqlquery;
    }
    
    public static function createInsertquerybasedonparams($tables="users",$fieldarray=array())
    {
        $sqlquery="insert into ".$tables." set ";
        if(count($fieldarray)>0)
        {
            foreach($fieldarray as $key=>$value)
    		{
    			$sqlquery.=$key."=:".$key.",";
    		}
            $sqlquery=substr($sqlquery,0,strlen($sqlquery)-1);
        }
        return $sqlquery;
    }
    
    public static function getBindarray($fieldarray=array())
    {
        $bindarray=array();
        foreach($fieldarray as $key=>$value)
    	{
    		$bindarray[":".$key]=$value;
    	}
        return $bindarray;
    }
    
    public static function createUpdatequerybasedonparams($tables="users",$fieldarray=array(),$conditionarray=array())
    {
        $sqlquery="update ".$tables." set ";
        if(count($fieldarray)>0)
        {
            foreach($fieldarray as $key=>$value)
    		{
    			$sqlquery.=$key."=:".$key.",";
    		}
            $sqlquery=substr($sqlquery,0,strlen($sqlquery)-1);
        }
        if(count($conditionarray)>0)
        {
            $sqlquery.=" where ";
            foreach($conditionarray as $key=>$value)
    		{
    			$sqlquery.=$key."=:".$key." and ";
    		}
            $sqlquery=substr($sqlquery,0,strlen($sqlquery)-4);
        }
        
        return $sqlquery;
    }
    
    public static function createDeletebasedonparams($tables="users",$conditionarray=array())
    {
        $sqlquery="delete from ".$tables." ";
        if(count($conditionarray)>0)
        {
            $sqlquery.=" where ";
            foreach($conditionarray as $key=>$value)
    		{
    			$sqlquery.=$key."=:".$key." and ";
    		}
            $sqlquery=substr($sqlquery,0,strlen($sqlquery)-4);
        }
        
        return $sqlquery;
    }
    
    /**
	*	Returns an array which represents a column from the result set 
	*
	*	@param  string $query
	*	@param  array  $params
	*	@return array
	*/	
		public static function column($query,$params = null)
		{
			self::Init($query,$params);
			$Columns = self::$sQuery->fetchAll(PDO::FETCH_NUM);		
			
			$column = null;

			foreach($Columns as $cells) {
				$column[] = $cells[0];
			}

			return $column;
			
		}	
       /**
	*	Returns an array which represents a row from the result set 
	*
	*	@param  string $query
	*	@param  array  $params
	*   	@param  int    $fetchmode
	*	@return array
	*/	
		public static function row($query,$params = null,$fetchmode = PDO::FETCH_ASSOC)
		{				
			self::Init($query,$params);
			return self::$sQuery->fetch($fetchmode);			
		}
       /**
	*	Returns the value of one single field/column
	*
	*	@param  string $query
	*	@param  array  $params
	*	@return string
	*/	
		public static function single($query,$params = null)
		{
			self::Init($query,$params);
			return self::$sQuery->fetchColumn();
		}
       /**	
	* Writes the log and returns the exception
	*
	* @param  string $message
	* @param  string $sql
	* @return string
	*/
	private static function ExceptionLog($message , $sql = "")
	{
		$exception  = 'Unhandled Exception. <br />';
		$exception .= $message;
		$exception .= "<br /> You can find the error back in the log.";

		if(!empty($sql)) {
			# Add the Raw SQL to the Log
			$message .= "\r\nRaw SQL : "  . $sql;
		}
        self::$path="/logs/";
			# Write into log
			self::write($message);

		return $exception;
	}
    
    public static function write($message) {
		$date = new DateTime();
		//$log = self::$path . $date->format('Y-m-d').".txt";
        $log = $date->format('Y-m-d').".txt";
        
		if(is_dir(self::$path)) {
		     chdir(self::$path);
			if(!file_exists($log)) {
			  	$fh  = fopen($log, 'w') or die("Fatal Error !");
              	$logcontent = "Time : " . $date->format('H:i:s')."\r\n" . $message ."\r\n";
				fwrite($fh, $logcontent);
				fclose($fh);
			}
			else {
				self::edit($log,$date, $message);
			}
		}
		else {
			  if(mkdir(self::$path,0777) === true) 
			  {
				 self::write($message);  
			  }	
		}
        
	 }
     
     private static function edit($log,$date,$message) {
        
        $logcontent = "Time : " . $date->format('H:i:s')."\r\n" . $message ."\r\n\r\n";
    	$logcontent = $logcontent . file_get_contents($log);
    	file_put_contents($log, $logcontent);
    }
    
}
?>